package task15;

import java.util.Scanner;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * Є матриця чисел типу double. 
 * Знайти кількість її рядків та стовпців, всі елементи яких різні.
 * 
 * @author Shpikulyk I.
 *
 */
public class Task {

	private static final int ROWS = 2;
	private static final int COLS = 2;
	
	public static void main(String[] args) {
		
//		double[][] matrix = initRandomMatrix();
		double[][] matrix = initByHand();
		
		print(matrix);
		
		FutureTask<Integer> rowCountTaskFuture 	= new FutureTask<Integer>(new RowCounter(matrix));
		FutureTask<Integer> colCountFuture 		= new FutureTask<Integer>(new ColCounter(matrix));
		
		(new Thread(rowCountTaskFuture)).start();
		(new Thread(colCountFuture)).start();
		
		try {
			System.out.println("Row count: " + rowCountTaskFuture.get());
			System.out.println("Col count: " + colCountFuture.get());
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}
	}

	private static double[][] initByHand() {
		double[][] matrix = new double[ROWS][COLS];
		Scanner scanner = null;

		try {
			scanner = new Scanner(System.in);
			
			for (int i = 0; i < ROWS; i++) {
				for (int j = 0; j < COLS; j++) {
					System.out.printf("Please insert value for matrix[%d][%d]:\t", i, j);
					double value = scanner.nextDouble();
					matrix[i][j] = value;
				}
			}
		} finally {
			if (scanner != null) scanner.close();
		}
		
		return matrix;
	}

	private static void print(double[][] matrix) {
		for (int i = 0; i < ROWS; i++) {
			for (int j = 0; j < COLS; j++) {
				System.out.printf("%.2f\t", matrix[i][j]);
			}
			System.out.println();
		}
		
	}

	private static double[][] initRandomMatrix() {
		double[][] matrix = new double[ROWS][COLS]; 
		
		for (int i = 0; i < ROWS; i++) {
			matrix[i] = new double[COLS];
			for (int j = 0; j < COLS; j++) {
				matrix[i][j] = Math.random();
			}
		}
		return matrix;
	}
	
	static class RowCounter implements Callable<Integer> {
		
		private double[][] matrix;

		public RowCounter(double[][] matrix) {
			this.matrix = matrix;
		}

		@Override
		public Integer call() throws Exception {
			int counter = 0;
			boolean hasDuplicates = false;
			
			for (int i = 0; i < ROWS; i++) {
				for (int j = 0; j < COLS; j++) {
					
					hasDuplicates = hasRowDuplicates(matrix, i, j);
					if ( hasDuplicates == true ) {
						break;
					}
				}
				
				if (hasDuplicates == true) {
					hasDuplicates = false;
					continue;
				}
				counter++;
			}
			return counter;
		}

		private boolean hasRowDuplicates(double[][] matrix, int row, int col) {
			double val = matrix[row][col];
			
			for (int j = 0; j < COLS; j++) {
				if (j == col) {
					continue;
				}
				
				if (val == matrix[row][j]) {
					return true;
				}
			}
			return false;
		}
		
	}
	
	static class ColCounter implements Callable<Integer> {
		
		private double[][] matrix;

		public ColCounter(double[][] matrix) {
			this.matrix = matrix;
		}

		@Override
		public Integer call() throws Exception {
			int counter = 0;
			boolean hasDuplicates = false;
			
			
			for (int j = 0; j < COLS; j++) {
				for (int i = 0; i < ROWS; i++) {
					if (hasColDuplicates(matrix, i, j) == true) {
						hasDuplicates = true;
						break;
					}
					
				}
				if (hasDuplicates == true) {
					hasDuplicates = false;
					continue;
				}
				counter++;
			}
			
			return counter;
		}

		private boolean hasColDuplicates(double[][] matrix2, int row, int col) {
			double val = matrix2[row][col];
			
			for (int i = 0; i < ROWS; i++) {
				if (i == row) {
					continue;
				}
				
				if (Double.compare(val, matrix2[i][col]) == 0) {
					return true;
				}
			}
			return false;
		}
		
	}

}
